/**
    Copyright (C) 2011  Alexander Vollmer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.jefb.service.impl;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

import org.jefb.entity.dto.FileToken;
import org.jefb.entity.dto.TransmissionCallback;
import org.jefb.service.INIOService;
import org.jefb.util.JefbUtils;
import org.jefb.util.service.impl.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class NIOService implements INIOService {

	private static Logger log = LoggerFactory.getLogger(NIOService.class);
	
	//services
	@Autowired
	private Config config;
	
	public void readToken(FileToken token, String absoluteFileName) {
		try {
			FileChannel fileChannel = new RandomAccessFile(absoluteFileName, "r").getChannel();
			Long newLength = config.getMaxTokenLength();
			if(config.getMaxTokenLength()+token.getOffset()>token.getFileLength()){
				newLength = token.getFileLength()-token.getOffset();
			}
			MappedByteBuffer targetBuffer = fileChannel.map(
					FileChannel.MapMode.READ_ONLY, token.getOffset(),
					newLength);
			
			token.setData(new byte[newLength.intValue()]);
			
			token.setLength(newLength);
			targetBuffer.get(token.getData());
			fileChannel.close();
		} catch (Exception e) {
			//TODO handle it
			e.printStackTrace();
		}
	}

	public void writeToken(FileToken fileTokenDTO,
			TransmissionCallback transmissionCallback) {
		//String fullFileName = config.getBaseDir() + fileTokenDTO.getFilename();
//		String fullFileName = config.getBaseDir() + "/cinbox"+fileTokenDTO.getPath()+JefbUtils.FILE_SEPARATOR+fileTokenDTO.getFilename();
		String fullFileName = "/cinbox"+fileTokenDTO.getPath()+JefbUtils.FILE_SEPARATOR+fileTokenDTO.getFilename();
//		String fullPath = fileTokenDTO.getFilename();
//		if(fullPath.startsWith("/")){
//			fullPath = fullPath.substring(1);
//		}
//		
//		String[] dirs = fullPath.split("/");
//		createDirs(config.getBaseDir() + "/cinbox"+fileTokenDTO.getPath());
		
		try {
			FileChannel targetChannel = new RandomAccessFile(fullFileName, "rw")
					.getChannel();
			MappedByteBuffer targetBuffer = targetChannel.map(
					FileChannel.MapMode.READ_WRITE, fileTokenDTO.getOffset(),
					fileTokenDTO.getLength());
			targetBuffer.put(fileTokenDTO.getData());
			targetChannel.close();
		} catch (FileNotFoundException fnfe) {
			transmissionCallback.getMessages().add(
					"Unable to find file named:" + fullFileName);
		} catch (IOException e) {
			transmissionCallback.getMessages().add(
					"Unable to access target file:" + fullFileName);
		} catch (Exception e) {
			transmissionCallback.getMessages().add(
					"Unexpected exception by writing token for file:"
							+ fullFileName);
		}

	}
	
	private void createDirs(String currentPath){
		File dir = new File(currentPath);
		dir.mkdirs();
//		if(index < dirs.length-1){
//			currentPath = currentPath + "/" + dirs[index];
//			File dir = new File(currentPath);
//			if(!dir.exists()){
//				dir.mkdir();
//			}
//			createDirs(dirs, index+1, currentPath);
//		}
	}

	public void setConfig(Config config) {
		this.config = config;
	}

	public Config getConfig() {
		return config;
	}

}
